package com.example.cadmin.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.cadmin.ScheduledTasks.DynamicTaskService;
import com.example.cadmin.ScheduledTasks.Task;
import com.example.cadmin.entity.*;
import com.example.cadmin.log.CabinetLog;
import com.example.cadmin.log.FileLogInsert;
import com.example.cadmin.mapper.*;
import com.example.cadmin.security.dto.JwtUserDto;
import com.example.cadmin.utils.DateFormat;
import com.example.cadmin.utils.Netty.Client;
import com.example.cadmin.utils.Netty.sendCmd;
import com.example.cadmin.utils.ResponseModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 智能选层柜 档案管理-服务实现类
 * </p>
 *
 * @author zzsoft
 * @since 2022-08-20
 */
@Service
@Slf4j
public class FileManageService {
    @Resource
    public ArchivesMapper archivesMapper;
    @Resource
    public MyUserMapper myUserMapper;
    @Resource
    public BorrowingRecordsMapper borrowingRecordsMapper;
    @Resource
    public sendCmd sendCmd;
    @Resource
    public HostService hostService;
    @Resource
    public ElectronArchivesMapper electronArchivesMapper;
    @Resource
    private DynamicTaskService dynamicTask;
    @Resource
    public SysParamsetMapper sysParamsetMapper;

    /**
     * 封装返回工具类
     */
    public ResponseModel resultUtil(String message) {
        if (message.contains("成功")) {
            return ResponseModel.success(message);
        } else {
            return ResponseModel.fail(message);
        }
    }

    public String getCabinetIp(HttpServletRequest request) {
        return Convert.toStr(request.getSession().getAttribute("cabinet"));
    }


    /**
     * 新增档案
     */
    public ResponseModel save(JSONObject data, HttpServletRequest request) throws IOException {
        HttpSession session = request.getSession();
        String number = (String) session.getAttribute("number");
        String[] selectPositions = data.getStr("select").split(",");
        String simpleUUID = IdUtil.simpleUUID();
        for (String position : selectPositions) {
            String[] positionArr = position.split("-");
            Archives archives = new Archives();
            archives.setReference(data.getStr("reference"));
            archives.setFileName(data.getStr("fileName"));
            archives.setFileNo(data.getStr("fileNo"));
            archives.setYear(DateFormat.getYear());
            archives.setEntryTime(DateFormat.getTime());
            archives.setUserId(data.getInt("userId"));
            archives.setProfile(data.getStr("profile"));
            if (data.get("status").equals("1")) {
                archives.setStatus(1);
            } else {
                archives.setStatus(data.getInt("status"));
            }
            archives.setNumber(number);
            archives.setCurrentLayer(positionArr[0]);
            archives.setCurrentColumn(positionArr[1]);
            archives.setElectronFile(0);
            archives.setUuid(simpleUUID);
            archivesMapper.insert(archives);
        }
        return ResponseModel.success("档案新增成功");
    }

    /**
     * 档案列表接口
     */
    public Map<String, Object> checkBorrowList(int page, int limit, String fileName, String number, String layer, String column,
                                               String userId, String startDate, String endDate, String year, String reference, String fileNo) {
        Map<String, Object> paramsMap = new HashMap<>();
        // 手动处理分页
        int offset = (page - 1) * limit;
        paramsMap.put("page", offset);
        paramsMap.put("limit", limit);
        if (StrUtil.isNotEmpty(fileName)) {
            paramsMap.put("file_name", fileName);
        }
        if (StrUtil.isNotEmpty(layer)) {
            paramsMap.put("current_layer", layer);
        }
        if (StrUtil.isNotEmpty(column)) {
            paramsMap.put("current_column", column);
        }
        if (StrUtil.isNotEmpty(number)) {
            paramsMap.put("number", number);
        }
        if (StrUtil.isNotEmpty(year)) {
            paramsMap.put("year", year);
        }
        if (StrUtil.isNotEmpty(startDate) && StrUtil.isNotEmpty(endDate)) {
            // 时间偏于一天
            Date date = DateUtil.parse(endDate, "yyyy-MM-dd");
            Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 1);
            String formatDate = DateUtil.formatDate(newDate);
            paramsMap.put("startTime", startDate);
            paramsMap.put("endTime", formatDate);
        }
        if (StrUtil.isNotEmpty(userId)) {
            paramsMap.put("userId", userId);
        }
        if (StrUtil.isNotEmpty(reference)) {
            paramsMap.put("reference", reference);
        }
        if (StrUtil.isNotEmpty(fileNo)) {
            paramsMap.put("file_no", fileNo);
        }
        List<Map<String, Object>> mapList = archivesMapper.archivesList(paramsMap);
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("code", 0);
        resMap.put("msg", "数据请求成功");
        resMap.put("data", mapList);
        resMap.put("count", archivesMapper.archivesListCount(paramsMap));
        return resMap;
    }

    /**
     * 删除功能档案
     */
    public ResponseModel delete(String id) throws IOException {
        String[] strings = id.split(",");
        List<String> idList = CollUtil.newArrayList(strings);
        for (String userId : idList) {
            Archives archives = archivesMapper.selectById(userId);
            archivesMapper.deleteById(archives.getId());
//            FileLogInsert.insert("档案管理", "删除" + archives.getFileName() + "档案", 3, archives.getNumber(), archives.getFileName());
            //删除电子档案
            electronArchivesMapper.delete(new QueryWrapper<ElectronArchives>().eq("archives_id", archives.getId()));
        }
        return ResponseModel.success("删除档案成功");
    }

    /**
     * 取出档案视图
     */
    public ModelAndView takeoutView(@RequestParam(value = "fileId") String fileId) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("FileManage/takeout");
        Map<String, Object> archivesInfo = archivesMapper.getArchivesInfo(fileId);
        modelAndView.addAllObjects(archivesInfo);
        // 获取用户信息
        JwtUserDto jwtUserDto = (JwtUserDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = jwtUserDto.getMyUser().getUserName();
        modelAndView.addObject("userName", userName);
        return modelAndView;
    }

    /**
     * 计算空位置
     */
    public Map<String, Object> calculateNull(Host host, List<String> archivesListExists) {
        // 计算空位置
        List<Object> layerColumnJoinList = new ArrayList<>();
        for (int layer = 1; layer <= Convert.toInt(host.getNumberOfLayers()); layer++) {
            for (int column = 1; column <= Convert.toInt(host.getNumberOfColumns()); column++) {
                layerColumnJoinList.add(layer + "-" + column);
            }
        }
//        List<String> layerColumnList = new ArrayList<>();
//        if (!archivesListExists.isEmpty()) {
//            layerColumnList.add(archives.getCurrentLayer() + "-" + archives.getCurrentColumn());
//
//        }
        List<Archives> archivesList = archivesMapper.selectList(new QueryWrapper<Archives>().eq("number", host.getNumber()));
        for (Archives archivesFor : archivesList) {
            String joinLayer = archivesFor.getCurrentLayer() + "-" + archivesFor.getCurrentColumn();
            //判断是不是自己本身 本身则忽略
            if (!archivesListExists.contains(joinLayer)) {
                layerColumnJoinList.remove(joinLayer);
            }
        }
        Map<String, Object> map = new LinkedHashMap<>();
        for (Object layer : layerColumnJoinList) {
            String[] splitJoin = layer.toString().split("-");
            if (!map.containsKey(splitJoin[0])) {
                List<Object> columnList = new ArrayList<>();
                columnList.add(splitJoin[1]);
                map.put(splitJoin[0], columnList);
            } else {
                JSONArray jsonArray = JSONUtil.parseArray(map.get(splitJoin[0]));
                jsonArray.add(splitJoin[1]);
                map.put(splitJoin[0], jsonArray);
            }
        }
        return map;
    }

    /**
     * 计算led位置
     */
    public static int calculateLEDPosition(int layer, int colum) {
        int index = (layer - 1) * 24 + colum;
        return index;
    }

    /**
     * 取出档案保存
     */
    public ResponseModel takeOutSave(JSONObject data, HttpServletRequest request) throws InterruptedException {
        Archives archives = archivesMapper.selectById(data.getInt("id"));
        List<Archives> archivesList = archivesMapper.selectList(new QueryWrapper<Archives>().eq("uuid", archives.getUuid()));
        for (Archives archivesFor : archivesList) {
            Host host = hostService.getOne(new QueryWrapper<Host>().eq("number", archives.getNumber()));
            //发送led打开命令
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("cmd", "led_open");
            map.put("cabinet_id", Convert.toInt(host.getNumber()));
            map.put("led_index", calculateLEDPosition(Convert.toInt(archivesFor.getCurrentLayer()), Convert.toInt(archivesFor.getCurrentColumn())));
            map.put("led_num", 1);
            String sendMap = JSONUtil.toJsonStr(map);
            sendCmd.send(sendMap, null, host.getIp());
            archivesFor.setStatus(1);
            archivesMapper.updateById(archivesFor);
            log.info(DateUtil.now() + " 取出档案成功");

            Thread.sleep(150);
        }
        //添加借阅记录
        JwtUserDto jwtUserDto = (JwtUserDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = jwtUserDto.getUsername();
        BorrowingRecords borrowingRecords = new BorrowingRecords();
        borrowingRecords.setFileName(data.getStr("fileName"));
        borrowingRecords.setDeptId(data.getInt("deptId"));
        borrowingRecords.setBorrowers(userName);
        borrowingRecords.setBorrowingDate(DateFormat.getTime());
        borrowingRecords.setPurpose(data.getStr("purpose"));
        borrowingRecords.setEstimatedDate(data.getStr("estimatedDate"));
        borrowingRecords.setCreateTime(DateFormat.getTime());
        borrowingRecords.setDataStatus(1);
        borrowingRecords.setStatus(1);
        borrowingRecords.setNumber(archives.getNumber());
        borrowingRecordsMapper.insert(borrowingRecords);
        // 添加定时任务
        Task task = new Task();
        Date date = DateUtil.date();
        SysParamset sysParamset = sysParamsetMapper.selectById(2);
        Date newDate = DateUtil.offset(date, DateField.SECOND, Convert.toInt(sysParamset.getParamValue()));
        LocalDateTime newDateTime = DateUtil.toLocalDateTime(newDate);
        task.setUuid(archives.getUuid());
        task.setStart(newDateTime);
        dynamicTask.add(task);
        return resultUtil("取出档案成功");
    }

    /**
     * 归还档案
     */
    public ResponseModel returnFile(JSONObject data, HttpServletRequest request) throws IOException, InterruptedException {
        List<Archives> archivesList = archivesMapper.selectList(new QueryWrapper<Archives>().eq("uuid", data.getStr("uuid")));
        Archives archivesDb = archivesList.get(0);
        String[] selectPositions = data.getStr("select").split(",");
        if (selectPositions.length == archivesList.size()) {
            for (Archives archives : archivesList) {
                int index = archivesList.indexOf(archives);
                String[] position = selectPositions[index].split("-");
                //判断此次归还位置是否和之前一样
                if (!archives.getCurrentLayer().equals(position[0])) {
                    archives.setCurrentLayer(position[0]);
                }
                if (!archives.getCurrentColumn().equals(position[1])) {
                    archives.setCurrentColumn(position[1]);
                }
                archives.setStatus(0);
                archivesMapper.updateById(archives);

                //发送归档命令
                Host host = hostService.getOne(new QueryWrapper<Host>().eq("number", archives.getNumber()));
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("cmd", "led_open");
                map.put("cabinet_id", Convert.toInt(host.getNumber()));
                map.put("led_index", calculateLEDPosition(Convert.toInt(archives.getCurrentLayer()), Convert.toInt(archives.getCurrentColumn())));
                map.put("led_num", 1);
                String sendMap = JSONUtil.toJsonStr(map);
                sendCmd.send(sendMap, null, host.getIp());
                log.info(DateUtil.now() + " 归档成功成功");
                Thread.sleep(150);
            }
        } else {
            archivesMapper.delete(new QueryWrapper<Archives>().eq("uuid", data.getStr("uuid")));
            for (String position : selectPositions) {
                String[] positionArr = position.split("-");
                Archives archives = new Archives();
                archives.setReference(archivesDb.getReference());
                archives.setFileName(archivesDb.getFileName());
                archives.setFileNo(archivesDb.getFileNo());
                archives.setYear(archivesDb.getYear());
                archives.setEntryTime(archivesDb.getEntryTime());
                archives.setUserId(archivesDb.getUserId());
                archives.setProfile(archivesDb.getProfile());
                archives.setStatus(0);
                archives.setNumber(archivesDb.getNumber());
                archives.setCurrentLayer(positionArr[0]);
                archives.setCurrentColumn(positionArr[1]);
                archives.setElectronFile(archivesDb.getElectronFile());
                archives.setUuid(archivesDb.getUuid());
                archivesMapper.insert(archives);
                //发送归档命令
                Host host = hostService.getOne(new QueryWrapper<Host>().eq("number", archives.getNumber()));
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("cmd", "led_open");
                map.put("cabinet_id", Convert.toInt(host.getNumber()));
                map.put("led_index", calculateLEDPosition(Convert.toInt(positionArr[0]), Convert.toInt(positionArr[1])));
                map.put("led_num", 1);
                String sendMap = JSONUtil.toJsonStr(map);
                sendCmd.send(sendMap, null, host.getIp());
                log.info(DateUtil.now() + " 归档成功成功");
                Thread.sleep(150);
            }
        }
        //添加借阅记录
        JwtUserDto jwtUserDto = (JwtUserDto) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = jwtUserDto.getUsername();
        BorrowingRecords borrowingRecords = new BorrowingRecords();
        borrowingRecords.setFileName(archivesDb.getFileName());
        borrowingRecords.setDeptId(data.getInt("deptId"));
        borrowingRecords.setBorrowers(userName);
        borrowingRecords.setBorrowingDate(DateFormat.getTime());
        borrowingRecords.setPurpose(data.getStr("purpose"));
        borrowingRecords.setCreateTime(DateFormat.getTime());
        borrowingRecords.setDataStatus(2);
        borrowingRecords.setStatus(1);//层 和 列
        borrowingRecords.setReturnLayerColumn(data.getStr("select"));
        borrowingRecords.setNumber(archivesDb.getNumber());
        borrowingRecordsMapper.insert(borrowingRecords);
        // 添加定时任务
        Task task = new Task();
        Date date = DateUtil.date();
        SysParamset sysParamset = sysParamsetMapper.selectById(2);
        Date newDate = DateUtil.offset(date, DateField.SECOND, Convert.toInt(sysParamset.getParamValue()));
        LocalDateTime newDateTime = DateUtil.toLocalDateTime(newDate);
        task.setUuid(archivesDb.getUuid());
        task.setStart(newDateTime);
        dynamicTask.add(task);
        return ResponseModel.success("归还档案成功");
    }

    /**
     * 修改档案视图
     */
    public ModelAndView editView(String id) {
        ModelAndView modelAndView = new ModelAndView();
        Map<String, Object> archives = archivesMapper.updateArchivesInfo(id);
        modelAndView.addAllObjects(archives);
        modelAndView.setViewName("FileManage/edit");
        List<MyUser> myUserList = myUserMapper.selectList(null);
        modelAndView.addObject("myUserList", myUserList);
        return modelAndView;
    }

    /**
     * 修改档案
     */
    public ResponseModel editSave(JSONObject data) {
        List<Archives> archivesList = archivesMapper.selectList(new QueryWrapper<Archives>().eq("uuid", data.getStr("uuid")));
        String[] selectPositions = data.getStr("select").split(",");
        if (selectPositions.length == archivesList.size()) {
            for (Archives archives : archivesList) {
                int index = archivesList.indexOf(archives);
                String[] position = selectPositions[index].split("-");
                //判断此次归还位置是否和之前一样
                if (!archives.getCurrentLayer().equals(position[0])) {
                    archives.setCurrentLayer(position[0]);
                }
                if (!archives.getCurrentColumn().equals(position[1])) {
                    archives.setCurrentColumn(position[1]);
                }
                archives.setReference(data.getStr("reference"));
                archives.setFileName(data.getStr("fileName"));
                archives.setFileNo(data.getStr("fileNo"));
                archives.setProfile(data.getStr("profile"));
                archives.setStatus(data.getInt("status"));
                archives.setUserId(data.getInt("userId"));
                int updateStatus = archivesMapper.updateById(archives);
            }
            return ResponseModel.success("修改档案名  " + data.getStr("fileName") + "  信息成功");

        }else {
            archivesMapper.delete(new QueryWrapper<Archives>().eq("uuid", data.getStr("uuid")));
            Archives  archives = archivesList.get(0);
            for (String position : selectPositions) {
                String[] positionArr = position.split("-");
                Archives archivesInsert = new Archives();
                archivesInsert.setReference(data.getStr("reference"));
                archivesInsert.setFileName(data.getStr("fileName"));
                archivesInsert.setFileNo(data.getStr("fileNo"));
                archivesInsert.setProfile(data.getStr("profile"));
                archivesInsert.setStatus(data.getInt("status"));
                archivesInsert.setUserId(data.getInt("userId"));
                archivesInsert.setYear(archives.getYear());
                archivesInsert.setEntryTime(archives.getEntryTime());
                archivesInsert.setNumber(archives.getNumber());
                archivesInsert.setCurrentLayer(positionArr[0]);
                archivesInsert.setCurrentColumn(positionArr[1]);
                archivesInsert.setElectronFile(archives.getElectronFile());
                archivesInsert.setUuid(archives.getUuid());
                archivesMapper.insert(archivesInsert);
            }
            return ResponseModel.success("修改档案名  " + data.getStr("fileName") + "  信息成功");
        }
    }

    /**
     * 档案新增树结构
     */
    public List<Map<String, Object>> positionTree(List<String> existsPositionList, HttpServletRequest request) {
        HttpSession session = request.getSession();
        String number = (String) session.getAttribute("number");
        Host host = hostService.getOne(new QueryWrapper<Host>().eq("number", number));
        Map<String, Object> map = calculateNull(host, existsPositionList);
        List<Map<String, Object>> layerList = new ArrayList<>();
        for (String layer : map.keySet()) {
            Map<String, Object> resultMap = new HashMap<>();
            int negativeNumber = Math.negateExact(Convert.toInt(layer));
            resultMap.put("name", layer);
            resultMap.put("value", negativeNumber);
            List<?> columnList = Convert.toList(map.get(layer));
            if (!columnList.isEmpty()) {
                List<Map<String, Object>> childrenList = new ArrayList<>();
                for (Object column : columnList) {
                    String joinLayerColumn = layer + "-" + column;
                    Map<String, Object> columnMap = new HashMap<>();
                    if (existsPositionList.contains(joinLayerColumn)) {
                        columnMap.put("selected", true);
                    }
                    columnMap.put("name", joinLayerColumn);
                    columnMap.put("value", joinLayerColumn);
                    columnMap.put("children", new ArrayList<>());
                    childrenList.add(columnMap);
                }
                resultMap.put("children", childrenList);
            } else {
                resultMap.put("children", new ArrayList<>());
            }
            layerList.add(resultMap);
        }
        return layerList;
    }
}
